package com.hm.shopping.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.querydsl.QPageRequest;
import org.springframework.stereotype.Service;

import com.hm.common.def.DataStatusDef;
import com.hm.common.exception.ErrorCode;
import com.hm.common.exception.ServiceException;
import com.hm.common.su.bean.PageInfo;
import com.hm.common.su.bean.PageInfo.PageInfoParam;
import com.hm.common.util.CommonUtil;
import com.hm.core.SdkConfig;
import com.hm.shopping.auto.su.BaseDomain;
import com.hm.shopping.def.OrderStateEnum;
import com.hm.shopping.domain.BuyGoodsOrderSnapshotDomain;
import com.hm.shopping.domain.GoodsIntroductionSnapshotDetailDomain;
import com.hm.shopping.domain.OrderLogisticsDomain;
import com.hm.shopping.domain.OrderSnapshotProcessHistoryDomain;
import com.hm.shopping.domain.QBuyGoodsOrderSnapshotDomain;
import com.hm.shopping.domain.QGoodsIntroductionSnapshotDetailDomain;
import com.hm.shopping.domain.QOrderLogisticsDomain;
import com.hm.shopping.domain.ShopcartDomain;
import com.hm.shopping.repository.BuyGoodsOrderSnapshotRepository;
import com.hm.shopping.repository.GoodsIntroductionSnapshotDetailRepository;
import com.hm.shopping.repository.OrderLogisticsRepository;
import com.hm.shopping.repository.OrderSnapshotProcessHistoryRepository;
import com.hm.shopping.repository.ShopcartRepository;
import com.hm.shopping.su.BeanUtil;
import com.hm.shopping.vo.GoodsIntroductionVo;
import com.hm.shopping.vo.OrderLogisticsVo;
import com.hm.shopping.vo.su.BuyGoodsSnapshotVo;
import com.hm.shopping.vo.su.BuyGoodsSnapshotVo.GoodsIntroductionSnapshotVo;
import com.hm.shopping.vo.su.SubmitOrderInfoVo;
import com.querydsl.core.types.dsl.BooleanExpression;

import lombok.extern.slf4j.Slf4j;

/**
 * @author shishun.wang
 * @date 2018年2月24日 上午11:33:43
 * @version 1.0
 * @describe
 */
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {

	@Autowired
	private UserService userService;

	@Autowired
	private ShopcartService shopcartService;

	@Autowired
	private ShopcartRepository shopcartRepository;

	@Autowired
	private GoodsIntroductionService goodsIntroductionService;

	@Autowired
	private OrderLogisticsRepository orderLogisticsRepository;

	@Autowired
	private BuyGoodsOrderSnapshotRepository buyGoodsOrderSnapshotRepository;

	@Autowired
	private OrderSnapshotProcessHistoryRepository orderSnapshotProcessHistoryRepository;

	@Autowired
	private GoodsIntroductionSnapshotDetailRepository goodsIntroductionSnapshotDetailRepository;

	@Override
	public String submitOrder(String buyerId, List<SubmitOrderInfoVo> submitOrderInfo) {
		if (CommonUtil.isAnyEmpty(buyerId, submitOrderInfo)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}
		log.info("{},提交订单:{}", buyerId, submitOrderInfo.toString());

		AtomicLong payAmount = new AtomicLong(0);
		BuyGoodsOrderSnapshotDomain buyGoodsOrderSnapshotDomain = new BuyGoodsOrderSnapshotDomain();
		{
			buyGoodsOrderSnapshotDomain.setOrderId(UUID.randomUUID().toString());
			buyGoodsOrderSnapshotDomain.setBuyerId(buyerId);
			buyGoodsOrderSnapshotDomain.setOrderPayState(OrderStateEnum.STAY_PAYMENT);

			buyGoodsOrderSnapshotDomain.setSnapshotDetails(submitOrderInfo.parallelStream().map(item -> {

				GoodsIntroductionSnapshotDetailDomain snapshotDetailDomain = new GoodsIntroductionSnapshotDetailDomain();
				{
					snapshotDetailDomain.setBuyerId(buyerId);
					snapshotDetailDomain.setOrderId(UUID.randomUUID().toString());
					snapshotDetailDomain.setBuyerMessage(item.getBuyerMessage());
					snapshotDetailDomain.setOrderState(OrderStateEnum.STAY_PAYMENT);

					ShopcartDomain shopcart = shopcartRepository.findOne(item.getShopcartId());
					GoodsIntroductionVo goodsIntroduction = goodsIntroductionService.getGoodsIntroduction(shopcart.getGoodsId());
					goodsIntroduction.setGoodsAttributes(goodsIntroduction.getGoodsAttributes().parallelStream().map(attr -> {
						attr.setAttributes(attr.getAttributes().parallelStream().map(attrDetail -> {
							attrDetail.setDefaultSelected(shopcart.getGoodsAttributes().contains(attrDetail.getName()));
							return attrDetail;
						}).collect(Collectors.toList()));
						return attr;
					}).collect(Collectors.toList()));

					snapshotDetailDomain.setShopsId(goodsIntroduction.getShopsId());
					snapshotDetailDomain.setGoodsIntroductionVo(goodsIntroduction);
					snapshotDetailDomain.setQuantity(shopcart.getQuantity());
					snapshotDetailDomain.setPayAmount(shopcart.getQuantity() * goodsIntroduction.getPromotionUnitPrice());
					snapshotDetailDomain.setBuyerAddress(userService.getUserAddressList(Long.valueOf(buyerId)).parallelStream().filter(address -> address.isRecentlyUse()).findAny().get());

					payAmount.addAndGet(shopcart.getQuantity() * goodsIntroduction.getPromotionUnitPrice());
				}

				BaseDomain.initBaseInfo(snapshotDetailDomain);
				goodsIntroductionSnapshotDetailRepository.save(snapshotDetailDomain);

				OrderSnapshotProcessHistoryDomain processHistoryDomain = new OrderSnapshotProcessHistoryDomain();
				{
					BaseDomain.initBaseInfo(processHistoryDomain);
					processHistoryDomain.setProcessInstructions("创建商品订单");
					processHistoryDomain.setOrderSnapshotId(snapshotDetailDomain.getId());
				}
				orderSnapshotProcessHistoryRepository.save(processHistoryDomain);

				return snapshotDetailDomain;
			}).collect(Collectors.toList()));
			buyGoodsOrderSnapshotDomain.setPayAmount(payAmount.get());
			BaseDomain.initBaseInfo(buyGoodsOrderSnapshotDomain);
		}
		buyGoodsOrderSnapshotRepository.save(buyGoodsOrderSnapshotDomain);

		// 清理购物车
		submitOrderInfo.parallelStream().forEach(item -> shopcartService.removeShopcart(item.getShopcartId()));

		return buyGoodsOrderSnapshotDomain.getId();
	}

	@Override
	public long personalOrderPay(String snapshotId) {
		if (CommonUtil.isEmpty(snapshotId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}
		BuyGoodsOrderSnapshotDomain orderSnapshotDomain = buyGoodsOrderSnapshotRepository.findOne(snapshotId);
		if (CommonUtil.isEmpty(orderSnapshotDomain)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
		}

		orderSnapshotDomain.setOrderPayState(OrderStateEnum.FINISH_PAYMENT);
		orderSnapshotDomain.setSnapshotDetails(orderSnapshotDomain.getSnapshotDetails().parallelStream().map(item -> {
			item.setOrderState(OrderStateEnum.FINISH_PAYMENT);
			{
				GoodsIntroductionSnapshotDetailDomain snapshotDetailDomain = goodsIntroductionSnapshotDetailRepository.findOne(item.getId());
				snapshotDetailDomain.setOrderState(OrderStateEnum.FINISH_PAYMENT);
				snapshotDetailDomain.setUpdateTime(new Date());// 更新支付完成时间
				goodsIntroductionSnapshotDetailRepository.save(snapshotDetailDomain);

				OrderSnapshotProcessHistoryDomain processHistoryDomain = new OrderSnapshotProcessHistoryDomain();
				{
					BaseDomain.initBaseInfo(processHistoryDomain);
					processHistoryDomain.setProcessInstructions("完成订单支付");
					processHistoryDomain.setOrderSnapshotId(snapshotDetailDomain.getId());
				}
				orderSnapshotProcessHistoryRepository.save(processHistoryDomain);
			}
			return item;
		}).collect(Collectors.toList()));
		buyGoodsOrderSnapshotRepository.save(orderSnapshotDomain);

		return orderSnapshotDomain.getPayAmount();
	}

	@Override
	public List<BuyGoodsSnapshotVo> getBuyerGoodsSnapshots(String buyerId, OrderStateEnum orderPayState) {
		if (CommonUtil.isAnyEmpty(buyerId, orderPayState)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		QBuyGoodsOrderSnapshotDomain qBuyGoodsOrderSnapshotDomain = QBuyGoodsOrderSnapshotDomain.buyGoodsOrderSnapshotDomain;
		List<BuyGoodsSnapshotVo> vos = new ArrayList<BuyGoodsSnapshotVo>();
		buyGoodsOrderSnapshotRepository.findAll(qBuyGoodsOrderSnapshotDomain.status.eq(DataStatusDef.ENABLE).and(qBuyGoodsOrderSnapshotDomain.buyerId.eq(buyerId)).and(qBuyGoodsOrderSnapshotDomain.orderPayState.eq(orderPayState))).forEach(item -> {
			BuyGoodsSnapshotVo vo = new BuyGoodsSnapshotVo();
			BeanUtil.copyProperties(item, vo);

			vo.setGoodsIntroductionSnapshotVos(item.getSnapshotDetails().parallelStream().map(detail -> {
				GoodsIntroductionSnapshotVo detailVo = new GoodsIntroductionSnapshotVo();
				BeanUtil.copyProperties(detail, detailVo);
				return detailVo;
			}).collect(Collectors.toList()));
			vos.add(vo);
		});
		return vos;
	}

	@Override
	public PageInfo<GoodsIntroductionSnapshotVo> queryBuyerGoodsSnapshots(PageInfoParam pageParam, String shopsId, OrderStateEnum orderPayState) {
		if (CommonUtil.isEmpty(shopsId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}
		QGoodsIntroductionSnapshotDetailDomain qGoodsIntroductionSnapshotDetailDomain = QGoodsIntroductionSnapshotDetailDomain.goodsIntroductionSnapshotDetailDomain;
		Pageable pageable = new QPageRequest(pageParam.getPage(), pageParam.getSize(), qGoodsIntroductionSnapshotDetailDomain.createTime.desc());

		BooleanExpression predicate = qGoodsIntroductionSnapshotDetailDomain.status.eq(DataStatusDef.ENABLE);
		if (Long.parseLong(shopsId) != SdkConfig.SUPER_ADMIN) {
			predicate = predicate.and(qGoodsIntroductionSnapshotDetailDomain.shopsId.eq(shopsId));
		}

		if (CommonUtil.isNotEmpty(orderPayState)) {
			predicate = predicate.and(qGoodsIntroductionSnapshotDetailDomain.orderState.eq(orderPayState));
		}

		Page<GoodsIntroductionSnapshotDetailDomain> page = goodsIntroductionSnapshotDetailRepository.findAll(predicate, pageable);
		if (CommonUtil.isEmpty(page.getContent())) {
			return new PageInfo<GoodsIntroductionSnapshotVo>();
		}

		return new PageInfo<GoodsIntroductionSnapshotVo>(page.getContent().parallelStream().map(item -> {
			GoodsIntroductionSnapshotVo vo = new GoodsIntroductionSnapshotVo();
			BeanUtil.copyProperties(item, vo);
			vo.setCreateTime(item.getCreateTime().getTime());
			vo.setUpdateTime(item.getUpdateTime().getTime());

			if (OrderStateEnum.FINISH_PAYMENT == item.getOrderState()) {
				vo.setOrderStateDesc("待发货");
			} else {
				vo.setOrderStateDesc(item.getOrderState().desc());
			}
			
			OrderLogisticsDomain orderLogisticsDomain = orderLogisticsRepository.findOne(QOrderLogisticsDomain.orderLogisticsDomain.ordersNapshotDetailId.eq(item.getId()));
			if(CommonUtil.isNotEmpty(orderLogisticsDomain)) {
				OrderLogisticsVo orderLogistics = new OrderLogisticsVo();
				BeanUtil.copyProperties(orderLogisticsDomain, orderLogistics);
				vo.setOrderLogistics(orderLogistics);
			}
			return vo;
		}).collect(Collectors.toList()), page.getTotalPages(), page.getTotalElements());

		// return new
		// PageInfo<GoodsIntroductionSnapshotVo>(page.getContent().parallelStream().map(item
		// -> {
		// return item.getGoodsIntroductionSnapshotVos().parallelStream().filter(goods
		// -> shopsId.equals(goods.getShopsId())).map(goodsInc -> {
		// GoodsIntroductionSnapshotVo vo = new GoodsIntroductionSnapshotVo();
		// BeanUtil.copyProperties(goodsInc, vo);
		// return vo;
		// }).collect(Collectors.toList());
		// }).reduce((all, items) -> {
		// if (CommonUtil.isNotEmpty(items)) {
		// all.addAll(items);
		// }
		// return all;
		// }).get(), page.getTotalPages(), page.getTotalElements());
	}

	@Override
	public void finishOrderCourier(OrderLogisticsVo orderLogistics) {
		if (CommonUtil.isAnyEmpty(orderLogistics.getLogisticsCompany(), orderLogistics.getLogisticsNumber(), orderLogistics.getOrdersNapshotDetailId())) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		GoodsIntroductionSnapshotDetailDomain snapshotDetailDomain = goodsIntroductionSnapshotDetailRepository.findOne(orderLogistics.getOrdersNapshotDetailId());
		if (CommonUtil.isEmpty(snapshotDetailDomain)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
		}

		snapshotDetailDomain.setOrderState(OrderStateEnum.FINISH_COURIER);
		snapshotDetailDomain.setUpdateTime(new Date());
		goodsIntroductionSnapshotDetailRepository.save(snapshotDetailDomain);

		OrderSnapshotProcessHistoryDomain processHistoryDomain = new OrderSnapshotProcessHistoryDomain();
		{
			BaseDomain.initBaseInfo(processHistoryDomain);
			processHistoryDomain.setProcessInstructions("商家配送完成,已发货");
			processHistoryDomain.setOrderSnapshotId(snapshotDetailDomain.getId());
		}
		orderSnapshotProcessHistoryRepository.save(processHistoryDomain);

		// 初始化物流信息
		OrderLogisticsDomain orderLogisticsDomain = new OrderLogisticsDomain();
		BeanUtil.copyProperties(orderLogistics, orderLogisticsDomain);
		orderLogisticsRepository.save(orderLogisticsDomain);
	}

	@Override
	public void finishOrder(String ordersNapshotDetailId) {
		if (CommonUtil.isEmpty(ordersNapshotDetailId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		GoodsIntroductionSnapshotDetailDomain snapshotDetailDomain = goodsIntroductionSnapshotDetailRepository.findOne(ordersNapshotDetailId);
		if (CommonUtil.isEmpty(snapshotDetailDomain)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
		}

		snapshotDetailDomain.setOrderState(OrderStateEnum.FINISH);
		snapshotDetailDomain.setUpdateTime(new Date());
		goodsIntroductionSnapshotDetailRepository.save(snapshotDetailDomain);

		OrderSnapshotProcessHistoryDomain processHistoryDomain = new OrderSnapshotProcessHistoryDomain();
		{
			BaseDomain.initBaseInfo(processHistoryDomain);
			processHistoryDomain.setProcessInstructions("订单流程结束");
			processHistoryDomain.setOrderSnapshotId(snapshotDetailDomain.getId());
		}
		orderSnapshotProcessHistoryRepository.save(processHistoryDomain);
	}

}
